import { Op } from 'sequelize';
import Menu from '@/models/system/menu.model';
import Role from '@/models/system/role.model';
import User from '@/models/system/user.model';
import RoleMenu from '@/models/system/roleMenu.model';
import UserRole from '@/models/system/userRole.model';
import { getLogger } from '@/utils/logger';

const logger = getLogger("menu-service", {
  console: false,
});
const consoleLogger = getLogger("menu-service");

// 前端路由对象接口
interface RouterVo {
  name?: string;
  path: string;
  hidden: boolean;
  redirect?: string;
  component: string;
  alwaysShow?: boolean;
  meta: {
    title: string;
    icon?: string;
    noCache?: boolean;
    link?: string | null;
  };
  children?: RouterVo[];
  query?: string;
}

// 菜单树结构接口
interface TreeSelect {
  id: number;
  label: string;
  disabled?: boolean;
  children?: TreeSelect[];
}

// 组件映射
const componentMap: Record<string, string> = {
  'Layout': 'Layout',
  'ParentView': 'ParentView',
  'InnerLink': 'InnerLink'
};

// 是否外链
const isExternal = (path: string): boolean => {
  return /^(https?:|mailto:|tel:)/.test(path);
};

class MenuService {
  /**
   * 根据条件查询菜单数据
   * @param params 查询参数
   */
  async selectMenuList(params: any) {
    const { menuName, visible, status, userId } = params;
    
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`查询菜单列表: ${JSON.stringify(params)}`);
      
      // 超级管理员显示所有菜单信息
      const isAdmin = await this.isAdmin(userId);
      
      const where: any = {
        // 只查询状态正常的菜单
      };
      
      if (menuName) {
        where.menuName = { [Op.like]: `%${menuName}%` };
      }
      if (visible !== undefined) {
        where.visible = visible;
      }
      if (status !== undefined) {
        where.status = status;
      }
      
      let menus;
      if (!isAdmin) {
        // 非管理员只能查看有权限的菜单
        const roleIds = await this.selectUserRoleIds(userId);
        
        menus = await Menu.findAll({
          where,
          include: [{
            model: Role,
            as: 'Roles',  // 使用正确的别名
            through: { attributes: [] },
            where: { roleId: { [Op.in]: roleIds } },
            required: true
          }],
          order: [['parentId', 'ASC'], ['orderNum', 'ASC']]
        });
      } else {
        // 管理员可以查看所有菜单
        menus = await Menu.findAll({
          where,
          order: [['parentId', 'ASC'], ['orderNum', 'ASC']]
        });
      }
      
      // 记录查询结果
      logger.info(`菜单列表查询完成: 总数=${menus.length}, 是否管理员=${isAdmin}`);
      
      // 直接返回菜单列表，不需要手动调用toJSON
      return menus;
    } catch (error) {
      consoleLogger.error(`查询菜单列表失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询菜单列表失败');
    }
  }

  /**
   * 根据用户ID查询菜单
   * @param userId 用户ID
   */
  async selectMenusByUserId(userId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`根据用户ID查询菜单: userId=${userId}`);
      
      // 查询用户拥有的所有角色ID
      const isAdmin = await this.isAdmin(userId);
      
      // 超级管理员拥有所有菜单权限
      if (isAdmin) {
        const menus = await this.selectMenuTreeAll();
        logger.info(`管理员用户查询菜单完成: userId=${userId}, 菜单数量=${menus.length}`);
        return menus;
      }
      
      // 查询用户关联的角色
      const roleIds = await this.selectUserRoleIds(userId);
      
      if (roleIds.length === 0) {
        logger.info(`用户无角色权限: userId=${userId}`);
        return [];
      }
      
      // 改用两步查询方法，避免复杂的多对多关联查询可能导致的问题
      // 第一步：查询角色关联的菜单ID
      const roleMenus = await RoleMenu.findAll({
        where: { roleId: { [Op.in]: roleIds } }
      });
      
      // 提取菜单ID
      const menuIds = [...new Set(roleMenus.map(rm => rm.menuId))];
      
      if (menuIds.length === 0) {
        logger.info(`用户角色无关联菜单: userId=${userId}, roleIds=${JSON.stringify(roleIds)}`);
        return [];
      }
      
      // 第二步：查询菜单
      const menus = await Menu.findAll({
        where: {
          menuId: { [Op.in]: menuIds },
          status: '0',
          visible: '0',
          menuType: { [Op.in]: ['M', 'C'] }  // 只查询目录和菜单
        },
        order: [['parentId', 'ASC'], ['orderNum', 'ASC']]
      });
      
      // 构建树结构
      const menuTree = this.buildMenuTree(menus);
      
      // 记录查询结果
      logger.info(`用户菜单查询完成: userId=${userId}, 菜单数量=${menuTree.length}, 角色数量=${roleIds.length}`);
      
      return menuTree;
    } catch (error) {
      consoleLogger.error(`根据用户ID查询菜单失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询用户菜单失败');
    }
  }

  /**
   * 构建前端所需要的路由
   * @param userId 用户ID
   */
  async buildMenus(userId: number): Promise<RouterVo[]> {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`构建前端路由: userId=${userId}`);
      
      // 获取菜单列表
      const menus = await this.selectMenusByUserId(userId);
      
      // 构建路由
      const routers = this.buildRouters(menus);
      
      // 记录构建结果
      logger.info(`构建前端路由完成: userId=${userId}, 路由数量=${routers.length}`);
      
      return routers;
    } catch (error) {
      consoleLogger.error(`构建前端路由失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('构建前端路由失败');
    }
  }

  /**
   * 处理路径，确保以单个斜杠开头，并避免多个连续斜杠
   * @param path 原始路径
   */
  private normalizePath(path: string): string {
    try {
      logger.debug(`规范化路径: path=${path}`);
      
      if (!path) return '/';
      
      // 如果是外部链接，不处理
      if (isExternal(path)) {
        return path;
      }
      
      // 移除开头和结尾的空格
      path = path.trim();
      
      // 确保以斜杠开头
      if (!path.startsWith('/')) {
        path = '/' + path;
      }
      
      // 替换连续多个斜杠为单个斜杠
      path = path.replace(/\/+/g, '/');
          
      return path;
    } catch (error) {
      consoleLogger.error(`规范化路径失败: ${error instanceof Error ? error.message : String(error)}`);
      // 返回原始路径，避免抛出异常影响主流程
      return path || '/';
    }
  }

  /**
   * 构建前端路由所需的菜单数据结构
   * @param menus 菜单列表
   */
  private buildRouters(menus: any[]): RouterVo[] {
    try {
      logger.debug(`开始构建路由: 菜单数量=${menus?.length || 0}`);
      
      const routers: RouterVo[] = [];
      
      if (!menus || menus.length === 0) {
        logger.warn('构建路由时未提供菜单列表');
        return [];
      }
      
      // 遍历菜单列表，构建路由
      menus.forEach(menu => {
        // 将Sequelize模型实例转换为纯JavaScript对象
        const menuObj = menu instanceof Menu ? menu.get({ plain: true }) : {...menu};
        
        const router: RouterVo = {
          path: this.getRouterPath(menuObj),
          component: this.getComponent(menuObj),
          hidden: menuObj.visible === '1',
          meta: {
            title: menuObj.menuName,
            icon: menuObj.icon,
            noCache: menuObj.isCache === '1'
          }
        };
        
        // 处理外链
        if (menuObj.isFrame === '1' && isExternal(menuObj.path)) {
          router.meta.link = menuObj.path;
        }
        
        // 路由名称，如果没有设置则使用驼峰格式的路径名
        router.name = menuObj.routeName || this.getRouteName(menuObj.path);
        
        // 处理查询参数
        if (menuObj.query) {
          router.query = menuObj.query;
        }
        
        // 处理子路由
        const cMenus = menuObj.children;
        if (cMenus && cMenus.length > 0 && menuObj.menuType === 'M') {
          // 目录类型菜单处理
          router.alwaysShow = true;
          router.redirect = 'noRedirect';
          router.children = this.buildRouters(cMenus);
        } else if (menuObj.menuType === 'C') {
          // 菜单类型处理
          if (menuObj.parentId == 0) {
            // 一级菜单处理，组件已在getComponent中设置为Layout
            const childrenList = [];
            // 子菜单路径，要去掉开头的'/'
            let childPath = menuObj.path;
            if (childPath.startsWith('/')) {
              childPath = childPath.substring(1);
            }
            
            const children: RouterVo = {
              path: childPath,
              component: menuObj.component || '',
              name: this.getRouteName(menuObj.routeName, menuObj.path),
              hidden: false,
              meta: {
                title: menuObj.menuName,
                icon: menuObj.icon,
                noCache: menuObj.isCache === '1',
              }
            };
                      
            // 处理查询参数
            if (menuObj.query) {
              children.query = menuObj.query;
            }
            
            childrenList.push(children);
            router.children = childrenList;
          }
        } else if (menuObj.parentId == 0 && isExternal(menuObj.path)) {
          // 处理外部链接
          router.meta = {
            title: menuObj.menuName,
            icon: menuObj.icon
          };
          router.path = '/';
          const childrenList = [];
          const routerPath = menuObj.path.replace(/http(s)?:\/\/(.*)/i, 'http$1://$2');
          const children: RouterVo = {
            path: routerPath,
            component: 'InnerLink',
            name: this.getRouteName(menuObj.routeName, routerPath),
            hidden: false,
            meta: {
              title: menuObj.menuName,
              icon: menuObj.icon,
              link: menuObj.path
            }
          };
          childrenList.push(children);
          router.children = childrenList;
        }
        
        routers.push(router);
      });
      
      logger.debug(`路由构建完成: 生成路由数量=${routers.length}`);
      
      return routers;
    } catch (error) {
      consoleLogger.error(`构建路由失败: ${error instanceof Error ? error.message : String(error)}`);
      // 返回空数组，避免抛出异常影响主流程
      return [];
    }
  }

  /**
   * 获取路由名称，如没有配置路由名称则取路由地址
   * @param name 路由名称
   * @param path 路由地址
   * @return 路由名称（驼峰格式）
   */
  private getRouteName(name?: string, path?: string): string {
    try {
      logger.debug(`获取路由名称: name=${name}, path=${path}`);
      
      const routerName = name || path;
      return routerName ? this.toCamelCase(routerName) : '';
    } catch (error) {
      consoleLogger.error(`获取路由名称失败: ${error instanceof Error ? error.message : String(error)}`);
      // 返回空字符串，避免抛出异常影响主流程
      return '';
    }
  }

  /**
   * 获取路由地址
   * @param menu 菜单信息
   */
  private getRouterPath(menu: any): string {
    try {
      logger.debug(`获取路由地址: menuId=${menu.menuId}, path=${menu.path}`);
      
      let routerPath = menu.path || '';
      
      // 外部链接直接返回
      if (isExternal(menu.path)) {
        return menu.path;
      }
      
      // 所有顶级菜单(parentId为0)的路径都需要以/开头
      if (menu.parentId == 0) {
        // 如果是一级菜单（类型为菜单C），且不是外链
        if (menu.menuType === 'C' && menu.isFrame === '0') {
          routerPath = '/';
        } 
        // 对于目录类型的顶级菜单，确保以/开头
        else {
          // 确保以斜杠开头，但避免重复斜杠
          if (!routerPath.startsWith('/')) {
            routerPath = '/' + routerPath;
          }
        }
      }
      
      return routerPath;
    } catch (error) {
      consoleLogger.error(`获取路由地址失败: ${error instanceof Error ? error.message : String(error)}`);
      // 返回原始路径或空字符串，避免抛出异常影响主流程
      return menu?.path || '';
    }
  }

  /**
   * 获取组件信息
   * @param menu 菜单信息
   */
  private getComponent(menu: any): string {
    try {
      logger.debug(`获取组件信息: menuId=${menu.menuId}, menuType=${menu.menuType}, parentId=${menu.parentId}`);
      
      // 顶级菜单一律使用Layout
      if (menu.parentId == 0) {
        return 'Layout';
      }
      
      // 非顶级菜单处理
      if (menu.component) {
        // 如果设置了组件，则使用设置的组件
        return menu.component;
      } else if (isExternal(menu.path)) {
        // 外部链接使用InnerLink
        return 'InnerLink';
      } else if (menu.menuType === 'M') {
        // 目录类型使用ParentView
        return 'ParentView';
      }
      
      // 默认返回空字符串
      return '';
    } catch (error) {
      consoleLogger.error(`获取组件信息失败: ${error instanceof Error ? error.message : String(error)}`);
      // 返回空字符串，避免抛出异常影响主流程
      return '';
    }
  }

  /**
   * 转换首字母大写的驼峰命名
   * @param str 输入字符串
   */
  private toCamelCase(str: string): string {
    try {
      if (!str) return '';
      
      // 移除非法字符
      str = str.replace(/[^a-zA-Z0-9]/g, ' ');
      
      // 转换为驼峰命名
      const words = str.split(' ').filter(Boolean);
      if (words.length === 0) return '';
      
      const result = words.map((word, index) => {
        const firstChar = word.charAt(0);
        const restChars = word.slice(1).toLowerCase();
        return firstChar.toUpperCase() + restChars;
      }).join('');
      
      logger.debug(`转换驼峰命名: 原始=${str}, 结果=${result}`);
      return result;
    } catch (error) {
      consoleLogger.error(`转换驼峰命名失败: ${error instanceof Error ? error.message : String(error)}`);
      // 返回原始字符串或空字符串，避免抛出异常影响主流程
      return str || '';
    }
  }

  /**
   * 查询所有菜单树结构
   * @param buildTree 是否构建树结构，默认为true
   */
  async selectMenuTreeAll(buildTree: boolean = true) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`查询所有菜单树: buildTree=${buildTree}`);
      
      const menus = await Menu.findAll({
        where: { 
          status: '0',
          menuType: { [Op.in]: ['M', 'C'] }  // 只查询目录和菜单
        },
        order: [['parentId', 'ASC'], ['orderNum', 'ASC']]
      });
      
      // 构建菜单树
      if (!menus || menus.length === 0) {
        logger.info('菜单列表为空，返回空数组');
        return [];
      }
      
      const result = buildTree ? this.buildMenuTree(menus) : menus;
      
      // 记录查询结果
      logger.info(`菜单树查询完成: 菜单数量=${menus.length}, 树节点数量=${buildTree ? result.length : '未构建'}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`查询所有菜单树失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询菜单树失败');
    }
  }

  /**
   * 根据角色ID查询菜单树信息
   * @param roleId 角色ID
   */
  async selectMenuTreeByRoleId(roleId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`根据角色ID查询菜单树: roleId=${roleId}`);
      
      // 检查roleId是否为有效数字
      if (isNaN(roleId)) {
        consoleLogger.error(`根据角色ID查询菜单树失败: roleId 不是有效的数字`);
        throw new Error('无效的角色ID');
      }
      
      // 查询角色是否为管理员
      const isAdmin = await this.isAdminRole(roleId);
      
      // 查询角色关联的菜单ID
      const roleMenus = isAdmin ? [] : await RoleMenu.findAll({
        where: { roleId }
      });
      const menuIds = roleMenus.map(rm => Number(rm.menuId)).filter(id => !isNaN(id));
      
      // 查询所有菜单
      const menus = await Menu.findAll({
        where: { 
          status: '0',
          menuType: { [Op.in]: ['M', 'C'] }  // 只查询目录和菜单
        },
        order: [['parentId', 'ASC'], ['orderNum', 'ASC']]
      });
      
      // 转换为前端所需的格式
      const menuTree = {
        checkedKeys: menuIds,
        menus: this.buildMenuTreeSelect(menus)
      };
      
      // 记录查询结果
      logger.info(`角色菜单树查询完成: roleId=${roleId}, 菜单数量=${menus.length}, 已选菜单数量=${menuIds.length}, 是否管理员=${isAdmin}`);
      
      return menuTree;
    } catch (error) {
      consoleLogger.error(`根据角色ID查询菜单树失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询角色菜单树失败');
    }
  }

  /**
   * 构建前端所需的树形结构
   * @param menus 菜单列表
   */
  buildMenuTree(menus: any[]) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`构建菜单树: 菜单数量=${menus?.length || 0}`);
      
      if (!menus || menus.length === 0) {
        logger.warn("构建菜单树：提供的菜单列表为空");
        return [];
      }
      
      // 将Sequelize模型实例转换为纯JavaScript对象，去除Sequelize特有的属性和方法
      const plainMenus = menus.map(menu => {
        return menu instanceof Menu ? menu.get({ plain: true }) : {...menu};
      });
      
      // 将菜单按ID存储到Map中便于查找
      const menuMap = new Map();
      plainMenus.forEach(menu => {
        if (menu && !isNaN(menu.menuId)) {
        menuMap.set(menu.menuId, {
          ...menu,
          children: []
        });
        } else {
          logger.warn(`跳过无效的菜单项: ${JSON.stringify(menu)}`);
        }
      });
      
      // 最终的树形结构
      const rootMenus: any[] = [];
      
      // 遍历所有菜单，构建树形结构
      menuMap.forEach(menu => {
        const parentId = menu.parentId || 0;
        
        if (parentId == 0) {
          // 父节点为0的是根菜单
          rootMenus.push(menu);
        } else {
          // 查找父菜单
          const parentMenu = menuMap.get(parentId);
          if (parentMenu) {
            // 将当前菜单添加到父菜单的children中
            if (!parentMenu.children) {
              parentMenu.children = [];
            }
            parentMenu.children.push(menu);
          } else {
            // 找不到父菜单，作为根菜单处理
            logger.warn(`菜单 ${menu.menuName}(${menu.menuId}) 的父菜单 ${parentId} 不存在，作为根菜单处理`);
            rootMenus.push(menu);
          }
        }
      });
      
      // 排序
      this.sortMenuTree(rootMenus);
      
      // 清理空的children数组
      this.cleanEmptyChildren(rootMenus);
      
      // 记录构建结果
      logger.info(`菜单树构建完成: 根菜单数量=${rootMenus.length}, 总菜单数量=${menus.length}`);
      
      return rootMenus;
    } catch (error) {
      consoleLogger.error(`构建菜单树失败: ${error instanceof Error ? error.message : String(error)}`);
      // 返回空数组，避免抛出异常影响主流程
      return [];
    }
  }
  
  /**
   * 递归对菜单树进行排序
   * @param menus 菜单树
   */
  private sortMenuTree(menus: any[]) {
    try {
      logger.debug(`对菜单树进行排序: 菜单数量=${menus?.length || 0}`);
      
      if (!menus || menus.length === 0) {
        return;
      }
      
      // 按orderNum排序
      menus.sort((a, b) => (a.orderNum || 0) - (b.orderNum || 0));
      
      // 递归排序子菜单
      menus.forEach(menu => {
        if (menu.children && menu.children.length > 0) {
          this.sortMenuTree(menu.children);
        }
      });
    } catch (error) {
      consoleLogger.error(`菜单树排序失败: ${error instanceof Error ? error.message : String(error)}`);
      // 不抛出异常，避免影响主流程
    }
  }

  /**
   * 清理空的children数组
   * @param menus 菜单树
   */
  private cleanEmptyChildren(menus: any[]) {
    try {
      logger.debug(`清理空的children数组: 菜单数量=${menus?.length || 0}`);
      
      if (!menus || menus.length === 0) {
        return;
      }
      
      menus.forEach(menu => {
        if (menu.children && menu.children.length === 0) {
          // 如果children为空数组，则删除该属性
          delete menu.children;
        } else if (menu.children && menu.children.length > 0) {
          // 递归处理子菜单
          this.cleanEmptyChildren(menu.children);
        }
      });
    } catch (error) {
      consoleLogger.error(`清理空children数组失败: ${error instanceof Error ? error.message : String(error)}`);
      // 不抛出异常，避免影响主流程
    }
  }

  /**
   * 构建前端所需的树形结构
   * @param menus 菜单列表
   */
  buildMenuTreeSelect(menus: any[]): TreeSelect[] {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`构建菜单下拉树: 菜单数量=${menus?.length || 0}`);
      
      // 判断输入是否已经是树形结构（有children属性的对象）
      const isAlreadyTree = menus.length > 0 && menus.some(menu => menu.children);
      const menuTree = isAlreadyTree ? menus : this.buildMenuTree(menus);
      const result = this.convertMenuTreeToSelect(menuTree);
      
      // 记录构建结果
      logger.info(`菜单下拉树构建完成: 树节点数量=${result.length}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`构建菜单下拉树失败: ${error instanceof Error ? error.message : String(error)}`);
      // 返回空数组，避免抛出异常影响主流程
      return [];
    }
  }

  /**
   * 将菜单树转换为前端所需的下拉树结构
   * @param menuTree 菜单树
   */
  private convertMenuTreeToSelect(menuTree: any[]): TreeSelect[] {
    try {
      logger.debug(`转换菜单树为下拉树: 菜单树节点数量=${menuTree?.length || 0}`);
      
      return menuTree.map(menu => {
        const treeSelect: TreeSelect = {
          id: menu.menuId,
          label: menu.menuName,
          disabled: false
        };
        
        if (menu.children && menu.children.length > 0) {
          treeSelect.children = this.convertMenuTreeToSelect(menu.children);
        }
        
        return treeSelect;
      });
    } catch (error) {
      consoleLogger.error(`转换菜单树为下拉树失败: ${error instanceof Error ? error.message : String(error)}`);
      // 返回空数组，避免抛出异常影响主流程
      return [];
    }
  }

  /**
   * 标记菜单树中已选中的菜单
   * @param menuTree 菜单树
   * @param selectedMenuIds 已选中的菜单ID
   */
  markCheckedMenus(menuTree: any[], selectedMenuIds: number[]) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`标记已选中菜单: 菜单树节点数量=${menuTree?.length || 0}, 已选中菜单数量=${selectedMenuIds?.length || 0}`);
      
      menuTree.forEach(menu => {
        menu.checked = selectedMenuIds.includes(menu.menuId);
        if (menu.children && menu.children.length > 0) {
          this.markCheckedMenus(menu.children, selectedMenuIds);
        }
      });
      
      // 记录标记结果
      logger.info(`标记已选中菜单完成: 菜单树节点数量=${menuTree.length}, 已选中菜单数量=${selectedMenuIds.length}`);
    } catch (error) {
      consoleLogger.error(`标记已选中菜单失败: ${error instanceof Error ? error.message : String(error)}`);
      // 不抛出异常，避免影响主流程
    }
  }

  /**
   * 根据菜单ID查询信息
   * @param menuId 菜单ID
   */
  async selectMenuById(menuId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`根据ID查询菜单: menuId=${menuId}`);
      
      logger.debug(`尝试查询菜单ID: ${menuId}, 类型: ${typeof menuId}`);
      
      // 检查menuId是否为有效数字
      if (isNaN(menuId)) {
        consoleLogger.error(`根据ID查询菜单失败: menuId "${menuId}" 不是有效的数字`);
        throw new Error('无效的菜单ID');
      }
      
      const menu = await Menu.findByPk(menuId);
      
      // 记录查询结果
      if (menu) {
        logger.info(`菜单查询成功: menuId=${menuId}, menuName=${menu.menuName}`);
        return menu;
      }
      
      logger.info(`未找到菜单: menuId=${menuId}`);
      return null;
    } catch (error) {
      consoleLogger.error(`根据ID查询菜单失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询菜单信息失败');
    }
  }

  /**
   * 根据用户ID查询权限
   * @param userId 用户ID
   */
  async selectPermsByUserId(userId: number): Promise<string[]> {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`根据用户ID查询权限: userId=${userId}`);
      
      // 判断是否为管理员
      const isAdmin = await this.isAdmin(userId);
      
      // 管理员拥有所有权限
      if (isAdmin) {
        logger.info(`管理员用户拥有所有权限: userId=${userId}`);
        return ['*:*:*'];
      }
      
      // 查询用户关联的所有菜单权限
      const perms = await Menu.findAll({
        attributes: ['perms'],
        include: [{
          model: Role,
          as: 'Roles',  // 使用正确的别名
          through: { attributes: [] },
          include: [{
            model: User,
            as: 'Users',  // 使用正确的别名
            through: { attributes: [] },
            where: { userId },
            required: true
          }],
          where: { status: '0' },
          required: true
        }],
        where: {
          status: '0',
          perms: {
            [Op.not]: ''
          }
        }
      });
      
      // 提取权限标识并去重
      const permsList = this.processPermissions(perms.map(menu => menu.perms).filter(Boolean) as string[]);
      
      // 记录查询结果
      logger.info(`用户权限查询完成: userId=${userId}, 权限数量=${permsList.length}`);
      
      return permsList;
    } catch (error) {
      consoleLogger.error(`根据用户ID查询权限失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询权限失败');
    }
  }

  /**
   * 处理权限标识，支持逗号分隔的多个权限
   * @param permissions 权限标识列表
   */
  private processPermissions(permissions: string[]): string[] {
    try {
      logger.debug(`处理权限标识: 权限数量=${permissions?.length || 0}`);
      
      const permsSet = new Set<string>();
      
      permissions.forEach(permission => {
        if (permission) {
          const permsSplit = permission.trim().split(',');
          permsSplit.forEach(perm => {
            if (perm) {
              permsSet.add(perm.trim());
            }
          });
        }
      });
      
      const result = Array.from(permsSet);
      logger.debug(`权限处理完成: 原始权限数量=${permissions.length}, 处理后权限数量=${result.length}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`处理权限标识失败: ${error instanceof Error ? error.message : String(error)}`);
      // 返回空数组，避免抛出异常影响主流程
      return [];
    }
  }

  /**
   * 是否存在菜单子节点
   * @param menuId 菜单ID
   */
  async hasChildByMenuId(menuId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`检查菜单子节点: menuId=${menuId}`);
      
      const count = await Menu.count({
        where: { 
          parentId: menuId
        }
      });
      
      // 记录查询结果
      logger.info(`菜单子节点检查完成: menuId=${menuId}, 子节点数量=${count}`);
      
      return count > 0;
    } catch (error) {
      consoleLogger.error(`检查菜单子节点失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('检查菜单子节点失败');
    }
  }

  /**
   * 查询菜单是否存在角色
   * @param menuId 菜单ID
   */
  async checkMenuExistRole(menuId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`检查菜单角色关联: menuId=${menuId}`);
      
      const count = await RoleMenu.count({
        where: { menuId }
      });
      
      // 记录查询结果
      logger.info(`菜单角色关联检查完成: menuId=${menuId}, 关联角色数量=${count}`);
      
      return count > 0;
    } catch (error) {
      consoleLogger.error(`检查菜单角色关联失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('检查菜单角色关联失败');
    }
  }

  /**
   * 校验菜单名称是否唯一
   * @param menuName 菜单名称
   * @param parentId 父菜单ID
   * @param menuId 菜单ID
   */
  async checkMenuNameUnique(menuName: string, parentId: number, menuId?: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`校验菜单名称唯一性: menuName=${menuName}, parentId=${parentId}, menuId=${menuId || '未提供'}`);
      
      const where: any = { 
        menuName, 
        parentId
      };
      
      if (menuId) {
        where.menuId = { [Op.ne]: menuId };
      }
      
      const menu = await Menu.findOne({ where });
      const isUnique = !menu;
      
      // 记录查询结果
      logger.info(`菜单名称唯一性校验完成: menuName=${menuName}, parentId=${parentId}, 是否唯一=${isUnique}`);
      
      return isUnique;
    } catch (error) {
      consoleLogger.error(`校验菜单名称唯一性失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('校验菜单名称唯一性失败');
    }
  }

  /**
   * 新增保存菜单信息
   * @param menu 菜单信息
   */
  async insertMenu(menu: any) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`新增菜单: menuName=${menu.menuName}, menuType=${menu.menuType}`);
      
      const result = await Menu.create(menu);
      
      // 记录操作结果
      logger.info(`菜单新增成功: menuId=${result.menuId}, menuName=${result.menuName}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`新增菜单失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('新增菜单失败');
    }
  }

  /**
   * 修改保存菜单信息
   * @param menu 菜单信息
   */
  async updateMenu(menu: any) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`修改菜单: menuId=${menu.menuId}, menuName=${menu.menuName}`);
      
      const result = await Menu.update(menu, {
        where: { menuId: menu.menuId }
      });
      
      // 记录操作结果
      logger.info(`菜单修改完成: menuId=${menu.menuId}, 影响行数=${result[0]}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`修改菜单失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('修改菜单失败');
    }
  }

  /**
   * 删除菜单
   * @param menuId 菜单ID
   */
  async deleteMenuById(menuId: number) {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`删除菜单: menuId=${menuId}`);
      
      const result = await Menu.destroy({
        where: { menuId }
      });
      
      // 记录操作结果
      logger.info(`菜单删除完成: menuId=${menuId}, 影响行数=${result}`);
      
      return result;
    } catch (error) {
      consoleLogger.error(`删除菜单失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('删除菜单失败');
    }
  }

  /**
   * 根据角色ID查询菜单权限
   * @param roleId 角色ID
   */
  async selectMenuPermsByRoleId(roleId: number): Promise<string[]> {
    try {
      // 使用consoleLogger记录操作开始
      consoleLogger.info(`根据角色ID查询菜单权限: roleId=${roleId}`);
      
      // 判断是否为管理员角色
      const isAdmin = await this.isAdminRole(roleId);
      
      // 管理员拥有所有权限
      if (isAdmin) {
        logger.info(`管理员角色拥有所有权限: roleId=${roleId}`);
        return ['*:*:*'];
      }
      
      // 查询角色关联的菜单权限
      const menus = await Menu.findAll({
        attributes: ['perms'],
        include: [{
          model: Role,
          as: 'Roles',  // 使用正确的别名
          through: { attributes: [] },
          where: { roleId, status: '0' },
          required: true
        }],
        where: {
          status: '0',
          perms: {
            [Op.not]: ''
          }
        }
      });
      
      // 提取权限标识并处理
      const permsList = this.processPermissions(menus.map(menu => menu.perms).filter(Boolean) as string[]);
      
      // 记录查询结果
      logger.info(`角色菜单权限查询完成: roleId=${roleId}, 权限数量=${permsList.length}`);
      
      return permsList;
    } catch (error) {
      consoleLogger.error(`查询角色菜单权限失败: ${error instanceof Error ? error.message : String(error)}`);
      throw new Error('查询角色菜单权限失败');
    }
  }

  /**
   * 判断用户是否为管理员
   * @param userId 用户ID
   */
  private async isAdmin(userId: number): Promise<boolean> {
    try {
      logger.debug(`判断用户是否为管理员: userId=${userId}`);
      
      // 直接判断是否为超级管理员（userId=1）
      if (userId === 1) {
        logger.debug(`用户是超级管理员: userId=${userId}`);
        return true;
      }
      
      // 查询用户关联的角色
      const userRoles = await UserRole.findAll({
        where: { userId },
        include: [{
          model: Role,
          as: 'Role',  // 使用正确的别名
          attributes: ['roleKey'],
          required: true
        }]
      });
      
      // 检查是否有admin角色
      const isAdminRole = userRoles.some(ur => {
        const role = ur.get('Role') as any;
        return role && role.roleKey === 'admin';
      });
      
      logger.debug(`用户管理员角色判断结果: userId=${userId}, 是否管理员=${isAdminRole}`);
      
      return isAdminRole;
    } catch (error) {
      consoleLogger.error(`判断用户是否为管理员失败: ${error instanceof Error ? error.message : String(error)}`);
      return false;
    }
  }

  /**
   * 判断角色是否为管理员角色
   * @param roleId 角色ID
   */
  private async isAdminRole(roleId: number): Promise<boolean> {
    try {
      logger.debug(`判断角色是否为管理员角色: roleId=${roleId}`);
      
      const role = await Role.findByPk(roleId);
      const isAdmin = role?.roleKey === 'admin';
      
      logger.debug(`角色管理员判断结果: roleId=${roleId}, 是否管理员=${isAdmin}`);
      
      return isAdmin;
    } catch (error) {
      consoleLogger.error(`判断角色是否为管理员角色失败: ${error instanceof Error ? error.message : String(error)}`);
      return false;
    }
  }

  /**
   * 查询用户的角色ID列表
   * @param userId 用户ID
   */
  private async selectUserRoleIds(userId: number): Promise<number[]> {
    try {
      logger.debug(`查询用户角色ID列表: userId=${userId}`);
      
      // 查询用户关联的角色
      const userRoles = await UserRole.findAll({
        where: { userId },
        include: [{
          model: Role,
          as: 'Role',  // 使用正确的别名
          where: { status: '0' },
          required: true
        }]
      });
      
      const roleIds = userRoles.map(ur => ur.roleId);
      
      logger.debug(`用户角色ID列表查询完成: userId=${userId}, 角色数量=${roleIds.length}`);
      
      return roleIds;
    } catch (error) {
      consoleLogger.error(`查询用户角色ID列表失败: ${error instanceof Error ? error.message : String(error)}`);
      return [];
    }
  }
}

export default new MenuService();